const redis = require("redis");


let dbclient;

/**
 * 初始化reids
 * @param {PORT:端口号,HOST:地址} config   
 */
function init(config){
    dbclient = redis.createClient(config);
    dbclient.on("error", function(err){
        console.log(err);
    })
    return dbclient;
}

function getDbClient(){
    return dbclient
}

function rpush(mname, list) {
    if(!mname) return null;
    return new Promise((resolve, reject) => {
        dbclient.rpush(mname, ...list, function(err,doc){
            if(err) {
                console.log(err);
                return reject(err);
            }
            resolve(doc);
        })
    })
}
function lpop(mname, list) {
    if(!mname) return null;
    return new Promise((resolve, reject) => {
        dbclient.lpop(mname,  function(err,doc){
            if(err) {
                console.log(err);
                return reject(err);
            }
            resolve(doc);
        })
    })
}

function lpush(mname, list) {
    if(!mname) return null;
    return new Promise((resolve, reject) => {
        dbclient.lpush(mname, ...list, function(err){
            if(err) {
                console.log(err);
                return reject(err);
            }
            resolve(null);
        })
    })
}

function llen(mname) {
    if(!mname) return null;
    return new Promise((resolve, reject) => {
        dbclient.llen(mname, function(err,doc){
            if(err) {
                console.log(err);
                return reject(err);
            }
            resolve(doc);
        })
    })
}

function ltrim(mname, start, stop) {
    if(!mname) return null;
    return new Promise((resolve, reject) => {
        dbclient.ltrim(mname, start, stop, function(err){
            if(err) {
                console.log(err);
                return reject(err);
            }
            resolve(null);
        })
    })
}

function  hmset(hashKey, key, value) {
    return new Promise((reslove, reject) => {
        dbclient.hmset(hashKey, key, value, function(err) {
            if(err) {
                console.log(err);
                return reject(err)
            }
            reslove(null);
        })
    })
}

function exists(key){
    return new Promise((reslove, reject) => {
        dbclient.exists(key, function(err,ret) {
            if(err) {
                console.log(err);
                return reject(err)
            }
            reslove(ret);
        })
    })
}

/**
 * 调用redis lrange方法
 * @param {*} mname 
 * @return promise
 */
 function lrange(lname, start, end) {
    try{
        if(!lname) return [];
        return new Promise((reslove, reject) => {
            dbclient.lrange(lname, start, end, function(err, list){
                if(err) {
                    console.log(err);
                    return reject(err);
                }
                reslove(list);
            })
        })
    }catch(err){
        console.log(err);
        throw err;
    }
}

/**
 * 调用redis lrange方法
 * @param {*} mname 
 * @return promise
 */
function lindex(lname, index) {
    try{
        if(!lname) return [];
        return new Promise((reslove, reject) => {
            dbclient.lindex(lname, index, function(err, doc){
                if(err) {
                    console.log(err);
                    return reject(err);
                }
                reslove(doc);
            })
        })
    }catch(err){
        console.log(err);
        throw err;
    }
}


function expire(key,value){
    return new Promise((reslove, reject) => {
        dbclient.expire(key,value, function(err,ret) {
            if(err) {
                console.log(err);
                return reject(err)
            }
            reslove(ret);
        })
    })
}

/**
 * 调用redis hgetall方法
 * @param {*} mname 
 * @return promise
 */
 function hgetall(mname){
    try{
        if(!mname) return null;
        return new Promise((resolve, reject) => {
            dbclient.hgetall(mname, (err, ret) => {
                if(err) {
                    console.log(err);
                    return reject(err);
                }
                resolve(ret);
            })
        })
    }catch(err){
        console.log(err);
        throw err;
    }
    
}

function  hincrby(hashKey, key, value) {
    return new Promise((reslove, reject) => {
        dbclient.hincrby(hashKey, key, value, function(err, doc) {
            if(err) {
                console.log(err);
                return reject(err)
            }
            reslove(doc);
        })
    })
}

function  hincrbyfloat(hashKey, key, value) {
    return new Promise((reslove, reject) => {
        dbclient.hincrbyfloat(hashKey, key, value, function(err, doc) {
            if(err) {
                console.log(err);
                return reject(err)
            }
            reslove(doc);
        })
    })
}

async function hdel(mname, key) {
    if(!mname) return null;
    return new Promise((reslove, reject) => {
        dbclient.hdel(mname, key, function(err) {
            if(err) {
                console.log(err);
                return reject(err)
            }
            reslove(null);
        })
    })
}

/**
 * 调用redis hget方法
 * @param {*} mname 
 * @return promise
 */
 async function hget(mname, key){
    try{    
        if(!mname) return null;
        return new Promise((resolve, reject) => {
            dbclient.hget(mname, key, (err, ret) => {
                if(err) {
                    return reject(err);
                }
                resolve(ret);
            })
        })
    }catch(err){
        console.log(err);
        throw err;
    }
}
/**
 * 调用redis hget方法
 * @param {*} mname 
 * @return promise
 */
 async function get(mname){
    try{    
        if(!mname) return null;
        return new Promise((resolve, reject) => {
            dbclient.get(mname, (err, ret) => {
                if(err) {
                    return reject(err);
                }
                resolve(ret);
            })
        })
    }catch(err){
        console.log(err);
        throw err;
    }
}
async function set(mname,value){
    try{    
        if(!mname) return null;
        return new Promise((resolve, reject) => {
            dbclient.set(mname, value, (err, ret) => {
                if(err) {
                    return reject(err);
                }
                resolve(ret);
            })
        })
    }catch(err){
        console.log(err);
        throw err;
    }
}
const USER_GAME_RECORD = "game_record"
async function saveGameRecord(userId,gameId, record){
    try{
        let {roomId} = await getUserRoom(userId)
        let gameKey = userId+"_"+gameId+"_"+roomId
        if(hasGameBetScore(gameId)){
            gameKey += "_"+record.difen
        }
        return hmset(USER_GAME_RECORD, gameKey , JSON.stringify(record))
    }catch(err){
        throw err;
    }
}

async function getGameRecord(userId, gameId, score){
    try{
        let {gameId, roomId} = await getUserRoom(userId)
        let gameKey = userId+"_"+gameId+"_"+roomId
        if(hasGameBetScore(gameId)){
            gameKey += "_"+score
        }
        let info = await hget(USER_GAME_RECORD, gameKey);
        if(!info) return null;
        let gameRecord = JSON.parse(info);
        let jpWins = gameRecord.jpWins || [];
        gameRecord.jpWinsHistory = gameRecord.jpWinsHistory ||  jpWins;
        delete gameRecord.jpWins;
        return gameRecord;
    }catch(err){
        throw err;
    }
}
async function removeGameRecord(userId, gameId, score){
    try{
        let {roomId} = await getUserRoom(userId)
        let gameKey = userId+"_"+gameId+"_"+roomId
        if(hasGameBetScore(gameId)){
            gameKey += "_"+score
        }
        await hdel(USER_GAME_RECORD, gameKey);
        return;
    }catch(err){
        throw err;
    }
}
function hasGameBetScore(gameId){
    if(gameId == 206){
        return true;
    }
}

async function getUserRoom(userId){
    try{
        const USER_ROOM ="user_room"
        let userRoomInfo = await hget(USER_ROOM, userId)
        if(!userRoomInfo) return {
            gameId:0,
            roomId:0
        }
        return JSON.parse(userRoomInfo);
    }catch(err){

    }
    
}


async function setUserBeatTime(userId) {
    return hmset("user_beat_time",userId, Date.now());
}
async function getAllUserBeatTime(userId) {
    return hgetall("user_beat_time");
}

async function getUserBeatTime(userId){
    return hget("user_beat_time", userId);
}

async function delUserBetTime(userId){
    return hdel("user_beat_time",userId)
}


function del(key) {
    if(!key) return null;
    return new Promise((reslove, reject) => {
        dbclient.del(key, function(err) {
            if(err) {
                console.log(err);
                return reject(err)
            }
            reslove(null);
        })
    })
}
function keys(key) {
    if(!key) return null;
    return new Promise((reslove, reject) => {
        dbclient.keys(key, function(err,keys) {
            if(err) {
                console.log(err);
                return reject(err)
            }
            reslove(keys);
        })
    })
}
function hkeys(key) {
    if(!key) return null;
    return new Promise((reslove, reject) => {
        dbclient.hkeys(key, function(err,keys) {
            if(err) {
                console.log(err);
                return reject(err)
            }
            reslove(keys);
        })
    })
}


/**
 * 调用redis incr方法
 * @param {*} key 
 * @return promise
 */
 async function incr(key, num) {
    try{
        if(!key) return null;
        num = num || 1;
        if(num !=1) {
            let currNum = await get(key);
            num = +currNum + num;
            return set(key, num)
        }else {
            return new Promise((resolve, reject) => {
                dbclient.incr(key, function(err, ret){
                    if(err) {
                        console.log(err);
                        return reject(err);
                    }
                    resolve(ret);
                });
            })
        }
    }catch(err){
        console.log(err);
        throw err;
    }
}


async function roomLock(userId){
    let num = await incr("room_lock_"+userId, 1);
    return num;
}

async function removeRoomLock(userId){
    return del("room_lock_"+userId);
}

module.exports = {
    init,
    hmset,
    hincrby,
    hget,
    get,
    set,
    hdel,
    del,
    hgetall,
    exists,
    expire,
    keys,
    hkeys,
    lrange,
    setUserBeatTime,
    getUserBeatTime,
    saveGameRecord,
    getGameRecord,
    delUserBetTime,
    getAllUserBeatTime,
    removeGameRecord,
    roomLock,
    removeRoomLock,
    getDbClient,
    rpush,
    lpush,
    ltrim,
    llen,
    lpop,
    lindex,
    hincrbyfloat,
}
